package com.example.springboot.system.controller;

import com.alibaba.excel.EasyExcel;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springboot.common.annotate.JwtToken;
import com.example.springboot.common.resp.Result;
import com.example.springboot.common.utils.JWTUtils;
import com.example.springboot.system.entity.BooknoEntity;
import com.example.springboot.system.entity.BooksEntity;
import com.example.springboot.system.entity.SortsEntity;
import com.example.springboot.system.entity.UserEntity;
import com.example.springboot.system.mapper.BooknoMapper;
import com.example.springboot.system.service.BooknoService;
import com.example.springboot.system.service.BooksService;
import com.example.springboot.system.service.SortsService;
import com.example.springboot.system.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 图书册表 前端控制器
 * </p>
 *
 * @author he
 * @since 2024-05-28
 */

@Tag(name = "书本管理")
@RestController
@RequestMapping("/booknoEntity")
public class BooknoController {

    @Data
    static class Bookno {
        private Integer id;
        private String code;
        private Integer booksId;
        private String booksName;
        private String name;
        private String userId;
        private String userName;
        private String borrowDate;
        private Integer borrow;
        private String createBy;
        private String createTime;
        private String updateBy;
        private String updateTime;
        private Integer undock;
        private Integer unlucky;
        private String remark;
    }

    @Autowired
    private BooknoMapper booknoMapper;

    @Autowired
    private BooknoService booknoService;

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    @Autowired
    private UserService userService;

    @Operation(summary = "列表分页")
    @PostMapping("/listPageBookno")
    public Result<?> listPageBookno(@RequestParam Integer page, @RequestParam Integer pageSize) {
        //分页参数
        Page<BooknoEntity> rowPage = new Page(page, pageSize);
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("undock", 1);
        rowPage = booknoMapper.selectPage(rowPage, wrapper);
        Page<Bookno> rowPageBookno = new Page(page, pageSize);
        BeanUtils.copyProperties(rowPage, rowPageBookno);
        List<BooknoEntity> records = rowPage.getRecords();
        ArrayList<Bookno> list = new ArrayList<>();
        for (int i = 0; i < records.size(); i++) {
            BooknoEntity entity = records.get(i);
            Bookno bookno = new Bookno();
            BeanUtils.copyProperties(entity, bookno);
            if (entity.getUserId() != null) {
                UserEntity user = userService.getById(entity.getUserId());
                bookno.setUserName(user.getName());
            }
            list.add(bookno);
        }
        rowPageBookno.setRecords(list);
        return Result.success("数据请求成功", rowPageBookno);
    }

    @JwtToken
    @Operation(summary = "查询编号")
    @PostMapping("/findByIDBookno/{param}")
    public Result<?> findByIDBookno(@PathVariable @Validated String param) {
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.like(("bookno_id"), param);
        wrapper.eq(("undock"), 1);
        if (booknoService.count(wrapper) == 0) return Result.success("查询成功，但符合条件数据为空");
        return Result.success("查询成功", booknoMapper.selectList(wrapper));
    }

    @JwtToken
    @Operation(summary = "查询名称")
    @PostMapping("/findByNameBookno/{param}")
    public Result<?> findByNameBookno(@PathVariable @Validated String param) {
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.like(("bookno_name"), param);
        wrapper.eq(("undock"), 1);
        if (booknoService.count(wrapper) == 0) return Result.failure("查询成功，但符合条件数据为空");
        return Result.success("查询成功", booknoMapper.selectList(wrapper));
    }

    @Operation(summary = "条件查询")
    @PostMapping("/findBookno")
    public Result<?> findBookno(@RequestBody BooknoEntity entity) {
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        if (entity.getCode() != "") wrapper.like(("bookno_code"), entity.getCode());
        if (entity.getName() != "") wrapper.like(("bookno_name"), entity.getName());
        if (entity.getUserId() != "") wrapper.like(("bookno_user_id"), entity.getUserId());
        if (entity.getBorrowDate() != "") wrapper.like(("bookno_borrow_date"), entity.getBorrowDate());
        if (entity.getBorrow() != 2) wrapper.like(("bookno_borrow"), entity.getBorrow());
        wrapper.like(("unlucky"), entity.getUnlucky());
        wrapper.eq(("undock"), 1);
        if (booknoService.count(wrapper) == 0) return Result.failure("查询成功，但符合条件数据为空");
        List<BooknoEntity> entities = booknoMapper.selectList(wrapper);
        ArrayList<Bookno> list = new ArrayList<>();
        for (int i = 0; i < entities.size(); i++) {
            BooknoEntity booknoEntity = entities.get(i);
            Bookno bookno = new Bookno();
            BeanUtils.copyProperties(booknoEntity, bookno);
            if (booknoEntity.getUserId() != null) {
                UserEntity user = userService.getById(booknoEntity.getUserId());
                bookno.setUserName(user.getName());
            }
            list.add(bookno);
        }
        return Result.success("查询成功", list);
    }

    @Data
    static class BooknoFind {
        private String code;
        private String name;
    }

    @Operation(summary = "用户查询")
    @PostMapping("/findBooknoUser")
    public Result<?> findBooknoUser(@RequestBody BooknoFind entity) {
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        if (entity.getCode() != "") wrapper.like(("bookno_code"), entity.getCode());
        if (entity.getName() != "") wrapper.like(("bookno_name"), entity.getName());
        if (booknoService.count(wrapper) == 0) return Result.failure("查询成功，但符合条件数据为空");
        List<BooknoEntity> list = booknoMapper.selectList(wrapper);
        ArrayList<Bookno> arrayList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            BooknoEntity booknoEntity = list.get(i);
            Bookno bookno = new Bookno();
            BeanUtils.copyProperties(booknoEntity, bookno);
            if (bookno.getUserId() != null) {
                UserEntity user = userService.getById(bookno.getUserId());
                bookno.setUserName(user.getName());
            }
            arrayList.add(bookno);
        }
        return Result.success("查询成功", arrayList);
    }

    @Autowired
    private BooksService booksService;

    @Autowired
    private SortsService sortsService;

    @JwtToken
    @Operation(summary = "保存数据")
    @PostMapping("/insert")
    public Result<?> insertBookno(@RequestBody @Validated BooknoEntity entity, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        String id = decodedJWT.getClaim("is").asString();
        String acc = decodedJWT.getClaim("acc").asString();
        String name = decodedJWT.getClaim("name").asString();
        //保存
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("bookno_id"), entity.getId());
        if (booknoService.count(wrapper) != 0) return Result.failure("保存失败，编号已存在");
        //设置创建者
        entity.setCreateBy(name);
        entity.setCreateTime(sdf.format(new Date()));
        //组装code
        BooksEntity books = booksService.getById(entity.getCode());
        SortsEntity sorts = sortsService.getById(books.getSortsId());
        entity.setBooksId(books.getId());
        entity.setCode(sorts.getCode() + "-" + books.getCode() + "-" + books.getVolume());
        entity.setCreateBy(name);
        entity.setCreateTime(sdf.format(new Date()));
        //更新书册总数
        books.setVolume(books.getVolume() + 1);
        if (entity.getBorrow() == 1) {
            books.setInventory(books.getInventory() + 1);
        }
        books.setUpdateBy(name);
        books.setUpdateTime(sdf.format(new Date()));
        //添加书册总数
        if (booknoService.save(entity) && booksService.updateById(books)) {
            return Result.success("保存成功");
        }
        return Result.failure("系统超时，保存失败");
    }

    @JwtToken
    @Operation(summary = "永久删除")
    @PostMapping("/delete/{param}")
    public Result<?> deleteBookno(@PathVariable @Validated String param) {
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("bookno_id"), param);
        if (booknoService.count(wrapper) == 0) return Result.failure("删除失败，编号不存在");
        BooknoEntity bookno = booknoService.getById(param);
        BooksEntity books = booksService.getById(bookno.getBooksId());
        books.setVolume(books.getVolume() - 1);
        if (bookno.getBorrow() == 1) {
            books.setInventory(books.getInventory() - 1);
        }
        if (booknoService.remove(wrapper) && booksService.updateById(books)) {
            return Result.success("删除成功");
        }
        return Result.failure("系统超时，删除失败");
    }

    @JwtToken
    @Operation(summary = "暂时删除")
    @PostMapping("/deleteTemp/{param}")
    public Result<?> deleteTempBookno(@PathVariable @Validated String param, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //修改
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("bookno_id"), param);
        if (booknoService.count(wrapper) == 0) return Result.failure("删除失败，编号不存在");
        BooknoEntity bookno = booknoService.getOne(wrapper);
        bookno.setUndock(0);
        //设置修改者
        String name = decodedJWT.getClaim("name").asString();
        bookno.setUpdateBy(name);
        bookno.setUpdateTime(sdf.format(new Date()));
        if (booknoService.updateById(bookno)) return Result.success("删除成功");
        return Result.failure("系统超时，删除失败");
    }

    @JwtToken
    @Operation(summary = "恢复列表")
    @PostMapping("/recoverList")
    public Result<?> recoverListBookno() {
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("undock", 0);
        return Result.success(booknoMapper.selectList(wrapper));
    }

    @JwtToken
    @Operation(summary = "恢复数据")
    @PostMapping("/recover/{param}")
    public Result<?> recoverBookno(@PathVariable @Validated String param, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //修改
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("bookno_id"), param);
        if (booknoService.count(wrapper) == 0) return Result.failure("恢复失败，编号不存在");
        BooknoEntity bookno = booknoService.getOne(wrapper);
        bookno.setUndock(1);
        //设置修改者
        String name = decodedJWT.getClaim("name").asString();
        bookno.setUpdateBy(name);
        bookno.setUpdateTime(sdf.format(new Date()));
        if (booknoService.updateById(bookno)) return Result.success("数据恢复成功");
        return Result.failure("系统超时，数据恢复失败");
    }

    @JwtToken
    @Operation(summary = "修改编号")
    @PostMapping("/update")
    public Result<?> updateBookno(@RequestBody @Validated BooknoEntity entity, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //设置修改者
        String name = decodedJWT.getClaim("name").asString();
        entity.setUpdateBy(name);
        entity.setUpdateTime(sdf.format(new Date()));
        //修改
        if (booknoService.updateById(entity)) return Result.success("修改成功");
        return Result.failure("系统超时，修改失败");
    }

    @Operation(summary = "导出数据")
    @PostMapping("exportExcel")
    public void exportExcelBookno(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("Excel数据表", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        List<BooknoEntity> list = booknoService.list();
        response.setHeader("Content-disposition", "attachment;filename*=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), BooknoEntity.class).sheet("Excel数据表").doWrite(list);
    }

    @JwtToken
    @Operation(summary = "导入数据")
    @PostMapping("/importExcel")
    public Result<?> importExcelBookno(MultipartFile file, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        try {
            //获取文件的输入流
            InputStream inputStream = file.getInputStream();
            List<BooknoEntity> list = EasyExcel.read(inputStream) //调用read方法
                    //注册自定义监听器，字段校验可以在监听器内实现
                    //.registerReadListener(new BooknoListener())
                    .head(BooknoEntity.class) //对应导入的实体类
                    .sheet(0) //导入数据的sheet页编号，0代表第一个sheet页，如果不填，则会导入所有sheet页的数据
                    .headRowNumber(1) //列表头行数，1代表列表头有1行，第二行开始为数据行
                    .doReadSync();//开始读Excel，返回一个List<T>集合，继续后续入库操作
            //模拟导入数据库操作
            String name = decodedJWT.getClaim("name").asString();
            for (BooknoEntity entity : list) {
                entity.setCreateBy(name);
                entity.setCreateTime(sdf.format(new Date()));
                booknoService.saveOrUpdate(entity);
            }
            return Result.success("导入成功");
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @JwtToken
    @Operation(summary = "用户书本")
    @PostMapping("/findBooknoBorrow")
    public Result<?> findBooknoBorrow(HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        String id = decodedJWT.getClaim("id").asString();//获取用户编号
        String acc = decodedJWT.getClaim("acc").asString();
        String name = decodedJWT.getClaim("name").asString();
        //获取用户
        QueryWrapper<BooknoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("bookno_user_id", id);
        return Result.success("数据请求成功", booknoMapper.selectList(wrapper));
    }

}
